import { jsonToString, urlSplit } from "utils-lib-js-lite";
import sha1 from "sha1";
import {
    TOKEN,
    UNSUPPORTED_MESSAGE_TYPES,
    WAIT_MESSAGE,
    NO_MESSAGE,
    HELP_MESSAGE,
} from "./config.js"

import { IExpressMiddlewareFn } from "./types.js";
import { Response } from "express";
import { checkEvent, replyText, sleep, toXML } from "./utils.js";
export const responseMiddleware = (res: Response, msg: string | object, state: number = 200, type: string = "text/plain") => {
    const _msg = typeof msg === "object" ? jsonToString(msg) : msg
    res.status(state).type(type)
    res.end(_msg ?? msg)
}
// 签名验证
export const sign: IExpressMiddlewareFn = (req, res, next) => {
    const params = urlSplit(req.url)
    const { method } = req
    if (method === "GET") {
        const _sign = sha1(
            new Array(TOKEN, params.timestamp, params.nonce).sort().join("")
        );
        if (_sign !== params.signature) {
            return responseMiddleware(res, "Forbidden", 403)
        }
        return responseMiddleware(res, params.echostr)
    }
    next()
}

// 处理微信事件消息
export const wechat: IExpressMiddlewareFn = async (req, res, next) => {
    const { method, url, body } = req
    
    if (method === "POST") {
        const params = urlSplit(url)
        const payload = body.xml;
        // 事件
        if (payload.MsgType === "event") {
            // 公众号订阅
            if (payload.Event === "subscribe") {
                return responseMiddleware(res, toXML(payload, HELP_MESSAGE));
            }
        }
        // 验证是否为重复推送事件
        const duplicatedEvent = await checkEvent(payload);
        if (duplicatedEvent) {
            console.error(`消息事件重复: `, payload);
            return responseMiddleware(res, "");
        }
        // 文本
        if (payload.MsgType === "text") {
            const newMessage = {
                msgid: payload?.MsgId,
                question: payload.Content.trim(),
                username: payload.FromUserName,
                sessionId: payload.FromUserName,
            };

            // 修复请求响应超时问题：如果 5 秒内 AI 没有回复，则返回等待消息
            const responseText = await Promise.race([
                replyText(newMessage),
                sleep(10000.0).then(() => WAIT_MESSAGE),
            ]);
            return responseMiddleware(res, toXML(payload, responseText));
        }

        // 暂不支持的消息类型
        if (payload.MsgType in UNSUPPORTED_MESSAGE_TYPES) {
            const responseText = UNSUPPORTED_MESSAGE_TYPES[payload.MsgType];
            return responseMiddleware(res, toXML(payload, responseText));
        }
        return responseMiddleware(res, toXML(payload, NO_MESSAGE));
    }
    next()
}

